﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections;
using System.Text;

namespace chesslibrary.cs
{
    public class board_chess
    {
        private Stack moves;
		private properties_table squares;
        public board_chess()
		{
			squares=new properties_table();
			Reset();
            moves=new Stack();
		}
        protected void Reset()
		{
			squares.Clear();
            for (int row=1;row<=8;row++)
			{
				for (int col=1;col<=8;col++)
				{
					properties_cell s=new properties_cell(row,col);
					squares.Add(s);
				}
			}
		}
        public properties_cell this[string s]
        {
            get { return squares[s]; }
        }
        public properties_cell this[int row,int col]
		{
			get{return squares[row,col];}
		}
        public properties_cell this[cell_chess c]
		{
			get{return squares[c];}
		}
        public properties_table this[color_pieces owner]
		{
			get
			{
				properties_table owned=new properties_table();

				foreach (properties_cell s in squares)
				{
					if (s.IsOwnedBy(owner))
					{
						owned.Add(s);
					}
				}
				return owned;
			}
		}
        public properties_cell KingSquare(color_pieces owner)
		{
			System.Diagnostics.Debug.Assert(squares.Count<=64);
			
			foreach (properties_cell s in squares)
			{
				if (s.IsOwnedBy(owner) && s.pieces_chess is pieces_king)
				{
					return s;
				}
			}
		    return null;
		}
        protected void setupBoard()
		{
			Reset();
            this["a1"].setPiece(new pieces_rook(color_pieces.White));
			this["h1"].setPiece(new pieces_rook(color_pieces.White));
			this["a8"].setPiece(new pieces_rook(color_pieces.Black));
			this["h8"].setPiece(new pieces_rook(color_pieces.Black));
            this["b1"].setPiece(new pieces_knight(color_pieces.White));
			this["g1"].setPiece(new pieces_knight(color_pieces.White));
			this["b8"].setPiece(new pieces_knight(color_pieces.Black));
			this["g8"].setPiece(new pieces_knight(color_pieces.Black));
            this["c1"].setPiece(new pieces_bishop(color_pieces.White));
			this["f1"].setPiece(new pieces_bishop(color_pieces.White));
			this["c8"].setPiece(new pieces_bishop(color_pieces.Black));
			this["f8"].setPiece(new pieces_bishop(color_pieces.Black));
            this["d1"].setPiece(new pieces_queen(color_pieces.White));
			this["d8"].setPiece(new pieces_queen(color_pieces.Black));
			this["e1"].setPiece(new pieces_king(color_pieces.White));
			this["e8"].setPiece(new pieces_king(color_pieces.Black));
            for (int col=1;col<=8;col++)
			{
				this[2,col].setPiece(new pieces_pawn(color_pieces.White));
				this[7,col].setPiece(new pieces_pawn(color_pieces.Black));
			}
		}
        public properties_cell north(properties_cell s)
		{
			return this[s.Row+1,s.Col];
		}
        public properties_cell northeast(properties_cell s)
		{
			return this[s.Row+1,s.Col+1];
		}
        public properties_cell east(properties_cell s)
		{
			return this[s.Row,s.Col+1];
		}
        public properties_cell southeast(properties_cell s)
		{
			return this[s.Row-1,s.Col+1];
		}
        public properties_cell south(properties_cell s)
		{
			return this[s.Row-1,s.Col];
		}
        public properties_cell southwest(properties_cell s)
		{
			return this[s.Row-1,s.Col-1];
		}
        public properties_cell west(properties_cell s)
		{
			return this[s.Row,s.Col-1];
		}
        public properties_cell northwest(properties_cell s)
		{
			return this[s.Row+1,s.Col-1];
		}
        public pieces_chess EnPassantPiece
		{
			get
			{
				if (moves.Count>0)
				{
					move_pieces m=(move_pieces)moves.Peek();

                    if (m is properties_pawn)
                    {
                        return m.pieces_chess;
                    }
                }
                return null;
            }
        }
        internal void ExecuteMove(move_pieces move)
		{
			if (move is functionmoves)
				ExecuteMove((functionmoves)move);
			if (move is properties_pawn)
				ExecuteMove((properties_pawn)move);
			if (move is EnPassant)
			    ExecuteMove((EnPassant)move);
            if (move is grade)
				ExecuteMove((grade)move);
            move.pieces_chess.Move();
			moves.Push(move);
            return;
		}
        public void UndoMove(move_pieces move)
		{
            if (move is functionmoves)
                UndoMove((functionmoves)move);       		
			if (move is properties_pawn)
				UndoMove((properties_pawn)move);
			if (move is EnPassant)
				UndoMove((EnPassant)move);
            if (move is grade)
				UndoMove((grade)move);
            move.pieces_chess.UndoMove();
			return;
		}
		private void ExecuteMove(functionmoves move)
		{
			properties_cell Begin=this[move.Begin];
			properties_cell end=this[move.End];
			Begin.setPiece(null);
			end.setPiece(move.pieces_chess);
		}
		private void ExecuteMove(properties_pawn move)
		{
			properties_cell End=this[move.End];
			End.setPiece(move.pieces_chess);
            properties_cell Begin=this[move.Begin];
			Begin.setPiece(null);
		}
		private void ExecuteMove(EnPassant move)
		{
		    properties_cell End=this[move.End];
			End.setPiece(move.pieces_chess);
            properties_cell Begin=this[move.Begin];
			Begin.setPiece(null);
			if (move.Owner==color_pieces.White)
			{
				properties_cell enpassant=this[5,move.End.Col];
				enpassant.setPiece(null);
			}
			else
			{
				properties_cell enpassant=this[4,move.End.Col];
				enpassant.setPiece(null);
			}
		}
        private void ExecuteMove(grade move)
		{
			properties_cell End=this[move.End];
			End.setPiece(move.GradePiece);
            properties_cell Begin=this[move.Begin];
			Begin.setPiece(null);
		}
        public bool UndoMove()
		{
			if (moves.Count>0)
			{
				move_pieces move=(move_pieces)moves.Pop();
				UndoMove(move);
				return true;
			}
            return false;
		}
        private void UndoMove(functionmoves move)
		{
			properties_cell Begin=this[move.Begin];
			properties_cell End=this[move.End];
            Begin.setPiece(move.pieces_chess);
			End.setPiece(move.Capturedpiece);
		}
       
		private void UndoMove(properties_pawn move)
		{
			properties_cell Begin=this[move.Begin];
			properties_cell End=this[move.End];
            Begin.setPiece(move.pieces_chess);
			End.setPiece(null);
		}
        private void UndoMove(EnPassant move)
		{
			properties_cell Begin=this[move.Begin];
			properties_cell End=this[move.End];
            Begin.setPiece(move.pieces_chess);
			End.setPiece(null);
            properties_cell enpassant;
			if (move.Owner==color_pieces.White)
			{
				enpassant=this[5,move.End.Col];
			}
			else
			{
				enpassant=this[4,move.End.Col];
			}
			EnPassant m=(EnPassant)move;
			enpassant.setPiece(m.Capturedpiece);
		}
        private void UndoMove(grade move)
		{
			properties_cell Begin=this[move.Begin];
			properties_cell End=this[move.End];
            Begin.setPiece(move.pieces_chess);
			End.setPiece(move.Capturedpiece);
		}
       
    }
}
